package com.amithkoujalgi.framework.rest.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Properties;

import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import com.amithkoujalgi.framework.rest.util.ConfigValidator;

public class Entry {
	private static Logger logger = Logger.getLogger(Entry.class);
	private static int defaultPort = 9999;

	public static void main(String[] args) throws InstantiationException,
			IllegalAccessException, ClassNotFoundException,
			NoSuchMethodException, SecurityException, IllegalArgumentException,
			InvocationTargetException, IOException {
		if (args.length < 2) {
			usage();
			return;
		}
		String portStr = args[0];
		String configFilePath = args[1];

		int port = defaultPort;

		try {
			port = Integer.parseInt(portStr);
		} catch (Exception e) {
			System.err
					.println("Port argument isn't an number. Defaulting port to "
							+ port + ".");
		}
		Properties p = loadProps(configFilePath);
		ApplicationContext.getInstance().setConfig(p);
		init(port, p);
		startApp(port, p);
	}

	private static void startApp(int port, Properties props) {
		try {
			ComponentInit init = new ComponentInit(port, props);
			ApplicationContext.getInstance().setComponentInit(init);
			init.startWebServer();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void init(int port, Properties p) {
		disableLoggingForAFewClasses();
		try {
			initCustomLogger(p);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void disableLoggingForAFewClasses() {
		Logger.getLogger(
				org.eclipse.jetty.util.component.AbstractLifeCycle.class)
				.setLevel(Level.OFF);
		org.apache.log4j.LogManager.getLogger("org.eclipse.jetty.server")
				.setLevel(Level.OFF);
	}

	private static Properties loadProps(String configFilePath) {
		Properties p1 = null;
		Properties p = new Properties();
		if (configFilePath != null) {
			try {
				p1 = new Properties();
				p1.load(new FileInputStream(new File(configFilePath)));
				for (java.util.Map.Entry<Object, Object> e : p1.entrySet()) {
					p.put(e.getKey(), e.getValue());
				}
			} catch (Exception e) {
				logger.error(e.getMessage() + " - Config not loaded.");
			}
		}
		return p;
	}

	private static void initCustomLogger(Properties p) throws IOException {
		String logDir = ConfigValidator.loadDefaultIfConfigPropNotFound(
				ConfigKey.LOG_DIRECTORY, AppConfig.DEFAULT_LOG_DIR);
		Layout lyt = new PatternLayout(
				"[%d{MMM dd, yyyy @ HH:mm:ss, SSS}ms] [%-5p] [%c] - %m%n");
		String logFilesRootDir = logDir + File.separator;
		FileAppender allLogsAppender = new FileAppender();
		allLogsAppender.setName("FileLogger");
		allLogsAppender.setFile(logFilesRootDir + "log-" + new Date().getTime()
				+ ".log");
		allLogsAppender.setLayout(lyt);
		allLogsAppender.setThreshold(Level.ALL);
		allLogsAppender.setAppend(true);
		allLogsAppender.activateOptions();
		Logger.getRootLogger().addAppender(allLogsAppender);

		FileAppender errAppender = new FileAppender();
		errAppender.setName("FileErrorLogger");
		errAppender.setFile(logFilesRootDir + "errors" + File.separator
				+ "log-" + new Date().getTime() + ".log");
		errAppender.setLayout(lyt);
		errAppender.setThreshold(Level.ERROR);
		errAppender.setAppend(true);
		errAppender.activateOptions();
		Logger.getRootLogger().addAppender(errAppender);
	}

	private static void usage() {
		System.err.println("Usage:");
		System.err.println("\t"
				+ "java -jar app.jar <port-number> <config-file-path>");
	}

}